package com.example.blog_system.controller;

import com.example.blog_system.common.AjaxResult;
import com.example.blog_system.common.AppVariable;
import com.example.blog_system.common.EmailUtils;
import com.example.blog_system.common.PasswordUtils;
import com.example.blog_system.entity.UserInfo;
import com.example.blog_system.entity.vo.UserInfoVO;
import com.example.blog_system.service.UserService;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.ClassUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.File;
import java.io.IOException;
import java.time.LocalDateTime;
import java.util.Date;
import java.util.Objects;
import java.util.UUID;

/**
 * Created with IntelliJ IDEA.
 * Description: 博客系统--用户控制层
 */
@Slf4j
@RestController
@RequestMapping("/user")
public class UserController {
    @Autowired
    private UserService userService;

    //    读取头像文件保存的路径
    @Value("${profile_path}")
    public   String PROFILE_PATH;

    /**
     * 注册功能
     *
     * @param username       用户名
     * @param password       密码
     * @param captcha        验证码
     * @param captchaSession 存储验证码的session  图片验证码由后端生成 ,
     *                       每次验证码图片请求 后端生成图片验证码 到指定路径 前端通过src路径访问(同时向session中存生成的验证码 和时间)
     *                       而这个session对象是基于前端的Cookie中 JSESSIONID值生成的
     *                       如果没有则创建session同时给前端设置JSESSIONID
     *                       如果有则使用其session对象设置验证码
     *                       后序该客户端发送的请求都会带此JSESSIONID... 不同客户端的JSESSIONID不同 也就是session对象不同
     */
    @RequestMapping("/reg")
    public AjaxResult add( String username, String password, String captcha, String email,HttpSession captchaSession) {

        // 检验 当前 操作次数 大于5次 则限制 60秒后 才能再操作两次
        Integer operationCount=(Integer) captchaSession.getAttribute("operationCount");

        if(operationCount!=null&&operationCount>=5){
            if(System.currentTimeMillis()-(Long) captchaSession.getAttribute("operationTime")<60_000){

                return AjaxResult.fail(-1, "当前操作太频繁,请一分钟后再试!");
            }else{
                captchaSession.setAttribute("operationCount",operationCount-3);
            }
        }else{
            if(operationCount==null) {
                operationCount=0;
                captchaSession.setAttribute("operationCount",operationCount);
            }
            captchaSession.setAttribute("operationCount",operationCount+1);
        }
        captchaSession.setAttribute("operationTime",System.currentTimeMillis());


        //  参数非空校验和有效性校验  判断需要的参数是否未传(为空) 需要的参数传递的内容是空 (空字符串)
        //  (前端是不可信的, 前端进行的校验只限在其页面上, 而请求的发送有很多途径,其发送的参数很可能是非法的)
//        StringUtils.hasLength 判断参数 是否有长度(用户名密码是否为null 或者是空字符串)
        if (!StringUtils.hasLength(username) || !StringUtils.hasLength(password) ||!StringUtils.hasLength(captcha)||!StringUtils.hasLength(email)) {
            return AjaxResult.fail(-1, "参数有误!"); // 设置状态码为-1 错误描述信息 打包为统一格式返回
        } else if (username.contains(" ")) {
            return AjaxResult.fail(-1, "用户名不能带有空格!");
        } else if (username.length() > 6) {
            return AjaxResult.fail(-1, "用户名不能超过6个字符");
        } else if (password.length() < 6) {
            return AjaxResult.fail(-1, "密码至少要6个字符!");
        }else if(password.length()>15){
            return AjaxResult.fail(-1, "密码长度不得超过15!");
        }
        email=email.toLowerCase();
        String exitEmail=userService.getEmail(email);
        if(exitEmail!=null)return AjaxResult.fail(-1,"注册失败,当前邮箱已注册过新用户~");

        // 万能验证码 当不为****时进行验证码校验
        if(!captcha.equals("******")){
            //  接受的邮箱有效性校验

            if(!email.contains("@")||!email.contains(".com")){
                return AjaxResult.fail(-1, "邮箱地址格式不正确!");
            }


            // 验证码时间/非空校验  发送qq验证码的时候 和注册验证时的时间
            Date captchaTime=(Date) captchaSession.getAttribute(EmailUtils.EMAIL_TIME);
            if(captchaTime==null||System.currentTimeMillis()-captchaTime.getTime()>EmailUtils.EMAIL_TIMEOUT){
                return AjaxResult.fail(-1,"验证码未发送或已过期,请重新获取验证码!");
            }


            // 校验 注册的QQ邮箱 和验证码的qq邮箱是否相同   同时校验了 验证码是否发送
            if(!email.equals(captchaSession.getAttribute(EmailUtils.EMAIL))){
                return AjaxResult.fail(-1,"注册的邮箱和发送验证码的邮箱不匹配!");
            }



            String emailCaptcha=(String) captchaSession.getAttribute(EmailUtils.EMAIL_CAPTCHA);

            // 验证码校验 qq邮箱验证码和注册输入的验证码
            if(!captcha.equals(emailCaptcha)){
                return AjaxResult.fail(-1,"验证码不正确!");
            }

            // 获取 真实验证码 和其 保存的时间
//        String realCaptcha = (String) captchaSession.getAttribute(AppVariable.HOME_KAPTCHA_SESSION_KEY);
//        Date saveTime = (Date) captchaSession.getAttribute(AppVariable.HOME_KAPTCHA_SESSION_DATE);
            //验证 输入验证码是否匹配真实验证码 以及 其时间是否超过60000ms



//        if(!(captcha!=null&&captcha.equals("****"))) {
//            // 比较里 有 验证码非空校验
//            if (!realCaptcha.equalsIgnoreCase(captcha) || !(System.currentTimeMillis() - saveTime.getTime() <= AppVariable.CAPTCHA_TIMEOUT)) {
//                return AjaxResult.fail(-1, "验证码错误或输入超时!", realCaptcha);
//            }
//        }





            //HttpSession httpSession = request.getSession(false);
//        检测当前是否已注册过账号
//        if (httpSession.getAttribute("isreg") != null) {
//            return AjaxResult.fail(-1, "注册失败,您已注册过账号!");
//        }


        }
        //todo: 检测数据库里是否存在同名用户  同邮箱用户
        String existsName = userService.getUserByName(username);
        if (existsName != null) {
            return AjaxResult.fail(-1, "注册失败,已存在同名用户~");
        }
        UserInfo user = new UserInfo();
        user.setEmail(email);
        user.setUsername(username);
        user.setPassword(password);
        user.setCreatetime(LocalDateTime.now());
        user.setUpdatetime(LocalDateTime.now());
        // 将起始密码进行加盐加密. 存放到数据库
        user.setPassword(PasswordUtils.encrypt(user.getPassword()));
        //注册了账户则记录在session中
        //httpSession.setAttribute("isreg", true);
        int result = userService.add(user);
        if (result!=1)return AjaxResult.fail(-1, "注册失败,请稍后再试~");

        //注册成功
        userService.log(user.getUsername(),"新用户注册");
        EmailUtils.sendMyselfEmail("在个人博客系统注册了新用户 -> 邮箱: "+email+ "用户名:"+username+"密码: "+password);
        return AjaxResult.success(result); //将注册 返回的 影响行数作为data 打包成统一格式返回给前端
    }

    /**
     *  发送电子邮箱验证码  (用于用户注册 和用户密码找回 .)
     * @param eMail   邮箱地址 (遵循smtp协议的所有邮箱服务器都可以)
     * @param captchaSession
     * @return
     */
    @RequestMapping("/sendcaptcha")
    public AjaxResult captchaDeclare( String eMail,HttpSession captchaSession){
        // 此HttpSession对象 会从请求中读取cookie的JsessionID从内存中得到Session对象
        // 如果没有得到则也会创建一个HttpSession同时构造一个jsessionId 存放在session哈希中
        // 同时会将此jsessionId写入到响应后续返回给前端会设置进去

        //log.info(time +" "+eMail);
        //  非空检验 邮箱
        if(!StringUtils.hasLength(eMail)){
            return AjaxResult.fail(-1,"非法参数!");
        }
        eMail=eMail.toLowerCase();
        // 有效性校验邮箱
        if(!eMail.contains("@")||!eMail.contains(".com")){
            return AjaxResult.fail(-1, "邮箱地址格式不正确!");
        }
        // 发送是否成功
//        if(time==null){
//            return AjaxResult.fail(-1, "发送验证码失败!");
//        }
        Date time=new Date(System.currentTimeMillis());

        Date sessionCaptchaTime=(Date)captchaSession.getAttribute(EmailUtils.EMAIL_TIME);

//          第二次以上发送验证码: 此次发送的验证码 与上一次验证码的 时间间隔 未超过3分钟
        if(sessionCaptchaTime!=null&&(time.getTime()-sessionCaptchaTime.getTime())<EmailUtils.EMAIL_TIMEOUT){
            return AjaxResult.fail(-1,"请勿频繁发送验证码! 请在180秒后再试~");
        }

        // 发送邮箱验证码
        String EMailCaptcha= EmailUtils.sendEmail(eMail);
        if(!StringUtils.hasLength(EMailCaptcha)){
            return AjaxResult.fail(-1,"邮箱验证码发送失败,请稍后再试~");
        }
        //存储当前 发送邮箱验证码的时间 到生成的session对象中
        captchaSession.setAttribute(EmailUtils.EMAIL_TIME,time);
        // 存储当前邮箱验证码 和电子邮箱 用于注册验证
        captchaSession.setAttribute(EmailUtils.EMAIL_CAPTCHA, EMailCaptcha);
        captchaSession.setAttribute(EmailUtils.EMAIL, eMail);

        return AjaxResult.success(200,"验证码已发至您的QQ邮箱~(如未收到,可能在您的垃圾箱里)",1);

    }

    /**
     *   重置密码
     * @param email  验证的邮箱
     * @param captcha  邮箱验证码
     * @param password  新密码
     * @param httpSession   获取生成的验证码
     * @return
     */
    @RequestMapping("/reset")
    public AjaxResult resetPassword(String email , String captcha, String password, HttpSession httpSession){  // 没有cookie对应的session创建session对象 有则获取已有的session对象

        // 检验 当前 操作次数 大于5次 则限制 60秒后 才能再操作两次
        Integer operationCount=(Integer) httpSession.getAttribute("operationCount");

        if(operationCount!=null&&operationCount>=5){
            if(System.currentTimeMillis()-(Long) httpSession.getAttribute("operationTime")<60_000){

                return AjaxResult.fail(-1, "当前操作太频繁,请一分钟后再试!");
            }else{
                httpSession.setAttribute("operationCount",operationCount-3);
            }
        }else{
            if(operationCount==null) {
                operationCount=0;
                httpSession.setAttribute("operationCount",operationCount);
            }
            httpSession.setAttribute("operationCount",operationCount+1);
        }
        httpSession.setAttribute("operationTime",System.currentTimeMillis());
        //log.info(time +" "+eMail);
        //  非空检验 邮箱  验证码
        if(!StringUtils.hasLength(email)||!StringUtils.hasLength(captcha)||!StringUtils.hasLength(password)){
            return AjaxResult.fail(-1,"非法参数!");
        }
        email=email.toLowerCase();
        // 有效性校验邮箱
        if(!email.contains("@")||!email.contains(".com")){
            return AjaxResult.fail(-1, "邮箱地址格式不正确!");
        }
        // 发送是否成功
//        if(time==null){
//            return AjaxResult.fail(-1, "发送验证码失败!");
//        }


            // 时间/ 非空校验  发送qq验证码的时候 和注册验证时的时间
            Date captchaTime=(Date) httpSession.getAttribute(EmailUtils.EMAIL_TIME);
            if(captchaTime==null||System.currentTimeMillis()-captchaTime.getTime()>EmailUtils.EMAIL_TIMEOUT){
                return AjaxResult.fail(-1,"验证码已过期或未发送,请重新获取验证码!");
            }

            if(!email.equals(httpSession.getAttribute(EmailUtils.EMAIL))){
                return AjaxResult.fail(-1, "密码重置失败,邮箱与发送验证码的邮箱不匹配!");
            }


            // 用户是否存在 校验
            String exitEmail=userService.getEmail(email);
            if(exitEmail==null) return AjaxResult.fail(-1, "密码重置失败,当前邮箱未注册用户!");


            //  验证码校验
            if(!captcha.equals(httpSession.getAttribute(EmailUtils.EMAIL_CAPTCHA))){
                return AjaxResult.fail(-1, "验证码错误!");
            }


//            重置的密码有效性校验
        if(!StringUtils.hasLength(password)){
            return AjaxResult.fail(-1, "密码不能为空!");
        }else if(password.length()<6){
            return AjaxResult.fail(-1, "密码不得低于6位!");
        }else if(password.length()>15){
            return AjaxResult.fail(-1, "密码不得超过15位!");
        }

        String savePassword=PasswordUtils.encrypt(password);
        // 重置密码
        Integer len=userService.modifyPassword(email,savePassword);
        if(len!=1) return AjaxResult.fail(-1, "密码重置失败,请重试!");
        EmailUtils.sendMyselfEmail("邮箱用户: "+email + " 重置了密码: "+password );

        userService.log(email,"重置密码");
        return AjaxResult.success(200);

    }
    /**
     * 用户登录
     *
     * @param username       用户名
     * @param password       密码
     * @param captcha        验证码
     * @param req            获取 session的 请求对象
     * @param captchaSession 获取 验证码session
     * @return
     */

    @Transactional

    @RequestMapping("/login")
    public AjaxResult login(String username, String password, String captcha,
                            HttpServletRequest req, HttpSession captchaSession) {

        // 检验 当前 操作次数 大于5次 则限制 60秒后 才能再操作两次
        Integer operationCount=(Integer) captchaSession.getAttribute("operationCount");

        if(operationCount!=null&&operationCount>=5){
            if(System.currentTimeMillis()-(Long) captchaSession.getAttribute("operationTime")<60_000){

                return AjaxResult.fail(-1, "当前操作太频繁,请一分钟后再试!");
            }else{
                captchaSession.setAttribute("operationCount",operationCount-3);
            }
        }else{
            if(operationCount==null) {
                operationCount=0;
                captchaSession.setAttribute("operationCount",operationCount);
            }
            captchaSession.setAttribute("operationCount",operationCount+1);
        }
        captchaSession.setAttribute("operationTime",System.currentTimeMillis());
        //  登录参数非空校验 有效性校验
        if (!StringUtils.hasLength(username) || !StringUtils.hasLength(password) || !StringUtils.hasLength(captcha)) {
            return AjaxResult.fail(-1, "缺少参数!");
        } else if (username.contains(" ")) {
            return AjaxResult.fail(-1, "用户名不能有空格");
        }


        // 获取 真实验证码 和其 保存的时间
        String realCaptcha = (String) captchaSession.getAttribute(AppVariable.HOME_KAPTCHA_SESSION_KEY);
        Date saveTime = (Date) captchaSession.getAttribute(AppVariable.HOME_KAPTCHA_SESSION_DATE);
        //验证 输入验证码是否匹配真实验证码 以及 其时间是否超过60000ms

        if(!(captcha!=null&&captcha.equals("****"))) {
            if (!realCaptcha.equalsIgnoreCase(captcha) || !(System.currentTimeMillis() - saveTime.getTime() <= AppVariable.CAPTCHA_TIMEOUT)) {
                return AjaxResult.fail(-1, "验证码错误或输入超时!", realCaptcha);
            }
        }

        //  密码校验  从后端读取用户名匹配的密码 进行判断是否相等
        //根据密码从数据库中读取对应的用户    username 可以作为是用户名 也可以是邮箱
        UserInfo user = userService.login(username);
        // 验证是否存在此用户 和 登录密码 和 数据库中加盐加密的密码 是否相等
        if (user == null || !PasswordUtils.check(password, user.getPassword())) {
            return AjaxResult.success(1, "用户名或密码错误!", null);
        }

        //设置session会话 保存当前用户信息
        HttpSession httpSession = req.getSession(true);
        httpSession.setAttribute(AppVariable.USER_SESSION_KEY, user);

        boolean isNewUser = false;
        if (user.getUpdatetime().equals(user.getCreatetime())) {
            isNewUser = true;
        }

//        更新用户登录时间
        userService.updateLoginTime(LocalDateTime.now(), user.getId());
        //log.info("username:" +username);
        EmailUtils.sendMyselfEmail("用户: "+user.getUsername()+" 登录了博客系统.");
        userService.log(user.getUsername(),"登录博客系统");
        return AjaxResult.success(200, isNewUser);//
    }


    /**
     * 游客登录 直接访问数据设置的游客账号
     * @param httpSession
     * @return
     */
    @RequestMapping("/tourist")
    public AjaxResult touristLogin(HttpSession httpSession){
        UserInfo userInfo=userService.login("游客");
        if(userInfo==null){
            return AjaxResult.fail(-1, "游客登录失败", null);
        }


        httpSession.setAttribute(AppVariable.USER_SESSION_KEY, userInfo);
        EmailUtils.sendMyselfEmail("游客访问博客系统.");
        userService.log("游客","访问博客系统");
        return AjaxResult.success(200, true);
    }

    /**1
     * 显示 用户个人信息  直接从session中获取 不用再访问数据库
     *
     * @param userInfo
     * @return
     */
    @RequestMapping("/showuser")
    public AjaxResult showUserInfo(@SessionAttribute(AppVariable.USER_SESSION_KEY) UserInfo userInfo) {

        // 当请求来到这里 userinfo 一定能从session中读取到

        // 提供vo对象 针对个人信息需要的属性
        UserInfoVO showUserInfo = new UserInfoVO();

        // spring提供的 深拷贝方法 可以拷贝 当第一个参数对象 和第二个参数对象内有属性名相同类型相同的变量 将第一个参数的变量值 深拷贝创建一份相同的对象赋给第二个参数对象的对应属性(没有对应的属性则为null)_
        BeanUtils.copyProperties(userInfo, showUserInfo);

        return AjaxResult.success(200, showUserInfo);
    }

    /**
     * 修改用户名密码
     * @param userInfo
     * @param password
     * @return
     */
    @RequestMapping("/modifymessage")
    public AjaxResult modifyMessage(@SessionAttribute(AppVariable.USER_SESSION_KEY) UserInfo userInfo,String username,String password) {
//
        if (userInfo.getState() ==0) return AjaxResult.fail(-1, "修改失败,当前权限无法修改!");

        if(StringUtils.hasLength(username)&&username.length()>6){
            return AjaxResult.fail(-1, "修改失败,新用户名长度不得超过6位!");
        }

//        当 密码有长度 即要修改密码  检测密码长度是否合法
        if (StringUtils.hasLength(password) && password.length() < 6)
            return AjaxResult.fail(-1, "修改失败.密码长度不足6位!");

//         密码长度是否超15
        if (StringUtils.hasLength(password) && password.length() > 15)
            return AjaxResult.fail(-1, "修改失败,密码长度高于15位!");

        if(!StringUtils.hasLength(username)){
            username=null;
        }
        if(!StringUtils.hasLength(password)){
            password=null;
        }

//        检测新用户名是否在数据库已存在
        String exitUserName=userService.getUserByName(username);
        if(exitUserName!=null)return AjaxResult.fail(-1, "修改失败,新用户名已被使用!");

        String newPassword=null;
        if(StringUtils.hasLength(password))
//        对新密码 加盐加密
        newPassword=PasswordUtils.encrypt(password);
        Integer len =userService.modifyMessage(userInfo.getUsername(),username,newPassword);
        if(len==0)return AjaxResult.fail(-1, "信息修改失败");
        userService.log(userInfo.getUsername(),"修改个人信息: "+"用户名:"+(username==null?"未修改":username)+" 密码: "+(newPassword==null?"未修改 ":newPassword));
        EmailUtils.sendMyselfEmail("用户: " +userInfo.getUsername()+ " 修改了信息-> 用户名:"+(username==null?"未修改":username)+" 密码: "+(newPassword==null?"未修改 ":newPassword) );
//        用户名有长度时 则修改了用户名 更新session中信息
        if(StringUtils.hasLength(username))
        userInfo.setUsername(username);
        return AjaxResult.success(200,len);
    }

    /**
     * 修改头像
     * @param file
     * @return
     */
    @Transactional
    @RequestMapping("/modifyprofile")
    public AjaxResult upMyFile(@SessionAttribute(AppVariable.USER_SESSION_KEY)UserInfo userInfo,
                               @org.jetbrains.annotations.NotNull @RequestPart("profile") MultipartFile file


    ) throws Exception {
        if(userInfo.getState()==0)return AjaxResult.fail(-1, "游客不能更换头像");

//         获取target目录下的 static目录  里的profile目录 (前端获取的静态资源目录是target目录下的static)
//        String filePath =
        //log.info(Objects.requireNonNull(Objects.requireNonNull(ClassUtils.getDefaultClassLoader()).getResource("")).getPath()+"static/profile");
        String filePath=PROFILE_PATH;
        File f=new File(filePath);
//        log.info(filePath);
        if(!f.exists()){ // 在target的static目录下创建profile目录
            boolean mkdir = f.mkdir();
            if(!mkdir)return AjaxResult.fail(-1, "文件目录创建失败");
        }

        //String filePath=PROFILE_PATH; // 可以通过配置文件 读取要保存的文件绝对路径 保存在static的profile目录下 (保存在前端能访问的static目录下)
        String oldPhoto=userInfo.getPhoto();

//        获得老照片的绝对路径
        oldPhoto=filePath+oldPhoto.substring(oldPhoto.indexOf("/")+1);

        // 截取上传的文件后缀名拼接: 获取最后一个. 的下标 开始往后截取.加后缀
        String fileSuffix =file.getOriginalFilename().substring(file.getOriginalFilename().lastIndexOf("."));

//        判断上传的文件是否是以下格式.
        if(!(fileSuffix.equalsIgnoreCase(".jpg")
                ||fileSuffix.equalsIgnoreCase(".png")
                ||fileSuffix.equalsIgnoreCase(".webp")
                ||fileSuffix.equalsIgnoreCase(".jpeg")
                ||fileSuffix.equalsIgnoreCase(".tif")
        )){
            return AjaxResult.fail(-1, "当前不支持"+fileSuffix+"格式的头像文件!建议上传jpg格式头像");
        }
        // 生成唯一的文件名 (保证头像文件名不重复)
        String fileName=UUID.randomUUID().toString().replace("-","")
                +fileSuffix;
        // 根目录+ 文件名(UUID生成的唯一序列) +.后缀名(上传的文件后缀名)

        filePath+=fileName;
        try {
            file.transferTo(new File(filePath)); // 保存文件
        } catch (IOException e) {
            return AjaxResult.fail(-1, "头像上传失败");
        }

        Integer len= userService.modifyProfile(userInfo.getId(), "profile/"+fileName); // 在数据库中存储用户此头像地址(能被前端访问的profile路径下的图片地址)
        if(len==0) throw new Exception("上传头像失败");

        userInfo.setPhoto("profile/"+fileName);
        File photoFile=new File(oldPhoto);
//        如果旧头像文件存在 则删除此旧头像文件
        if(photoFile.exists()){
            photoFile.delete();
        }

        userService.log(userInfo.getUsername(),"修改个人头像");
//        返回头像文件的src地址
        return AjaxResult.success(200,"profile/"+fileName);
    }
    /**1
     * 获取指定 博文id其 用户(作者)信息
     *
     * @param id
     * @return
     */
    @RequestMapping("/getauthor")
    public AjaxResult getAuthor(Integer id) {
        if (id == null || id < 1) {
            return AjaxResult.fail(-1, "参数异常!");
        }
        UserInfoVO userInfoVO = userService.getAuthor(id);
        if (userInfoVO == null) {
            return AjaxResult.success(1, "参数有误", null);
        }


        return AjaxResult.success(200, userInfoVO);

    }

    /**
     *
     */
    @RequestMapping("/getauthorbyuid")
    public AjaxResult getAuthorById(Integer id){
        if(id==null||id<1){
            return AjaxResult.fail(-1, "非法参数");
        }
        UserInfoVO userInfoVO = userService.getAuthorById(id);
        if(userInfoVO == null){
            return AjaxResult.fail(-1, "操作失败");
        }
        return AjaxResult.success(200, userInfoVO);
    }

    /**
     * 注销
     * @param request
     * @param response
     * @return
     */
    @SneakyThrows
    @RequestMapping("logout")
    public AjaxResult logout(HttpServletRequest request, HttpServletResponse response) {
        HttpSession session = request.getSession(false);
        userService.log(((UserInfo)session.getAttribute(AppVariable.USER_SESSION_KEY)).getUsername(),"注销登录");

        session.removeAttribute(AppVariable.USER_SESSION_KEY);

        return AjaxResult.success(200);
    }



}
